home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
x68000.arc
/
SOURCE.ARC
/
SRECORD.MOD
< prev
next >
Wrap
Text File
|
1986-01-23
|
8KB
|
283 lines
IMPLEMENTATION MODULE Srecord;
(* Creates Motorola S-records of program: *)
(* S0 = header record, *)
(* S2 = code/data records (24 bit address), *)
(* S8 = termination record (24 bit address). *)
FROM FileSystem IMPORT
File, WriteChar;
FROM Strings IMPORT
Length;
FROM LongNumbers IMPORT
LONG, LongAdd, LongSub, LongInc, LongDec, LongClear,
LongCompare, CardToLong, LongPut;
IMPORT ASCII;
CONST
CountMAX = 16;
SrecMAX = CountMAX * 2;
XrecMAX = SrecMAX;
VAR
StartAddr : LONG; (* address that record starts on *)
TempAddr : LONG; (* running address of where we are now *)
CheckSum : LONG;
Count : CARDINAL; (* count of HEX-pairs in S-record *)
Sdata : ARRAY [1..SrecMAX] OF INTEGER; (* S-record data, HEX digits *)
Sindex : CARDINAL; (* index for Sdata array *)
Xdata : ARRAY [1..XrecMAX] OF INTEGER; (* Overflow for Sdata *)
Xindex : CARDINAL; (* index for Xdata array *)
Boundary : BOOLEAN; (* marks Address MOD 16 boundary of S-record *)
LZero : LONG; (* used as a constant = 0 *)
PROCEDURE Complement; (* CheckSum *)
BEGIN
LongSub (LZero, CheckSum, CheckSum); (* 2's Complement *)
LongDec (CheckSum, 1); (* Make it 1's Complement *)
END Complement;
PROCEDURE AppendSdata (Data : LONG; n : CARDINAL) : BOOLEAN;
(* Transfers data to Sdata, and updates Count & CheckSum. *)
(* If no room: Data goes to Xdata & FALSE returned. *)
VAR
T : LONG; (* temporary -- used only as a 2 digit HEX number *)
BEGIN
T := LZero;
WHILE (n # 0) AND (Count # CountMAX) AND (NOT Boundary) DO
Sdata[Sindex] := Data[n];
Sdata[Sindex - 1] := Data[n - 1];
T[2] := Data[n]; T[1] := Data[n - 1];
LongAdd (T, CheckSum, CheckSum);
DEC (n, 2);
DEC (Sindex, 2);
INC (Count);
LongInc (TempAddr, 1);
IF TempAddr[1] = 0 THEN (* i.e., TempAddr MOD 16 = 0 *)
Boundary := TRUE;
END;
END;
IF (Count = CountMAX) OR (Boundary) THEN
WHILE n > 0 DO (* Add Data to Xdata (in reverse) *)
INC (Xindex);
Xdata[Xindex] := Data[n];
DEC (n);
END;
RETURN FALSE; (* Sdata is full *)
ELSE
RETURN TRUE;
END;
END AppendSdata;
PROCEDURE DumpSdata (VAR f : File);
(* Writes an S2 record to the file *)
VAR
T : LONG; (* temporary -- used to output Count & CheckSum *)
i, j : CARDINAL;
BEGIN
IF Count = 0 THEN
RETURN; (* nothing to dump *)
END;
WriteChar (f, 'S');
WriteChar (f, '2');
CardToLong (Count + 4, T); (* extra for Address & Checksum *)
LongPut (f, T, 2);
LongAdd (T, CheckSum, CheckSum); (* Add Count to CheckSum *)
LongPut (f, StartAddr, 6);
(* Add Address to CheckSum *)
T := LZero;
T[1] := StartAddr[1]; T[2] := StartAddr[2];
LongAdd (T, CheckSum, CheckSum);
T[1] := StartAddr[3]; T[2] := StartAddr[4];
LongAdd (T, CheckSum, CheckSum);
T[1] := StartAddr[5]; T[2] := StartAddr[6];
LongAdd (T, CheckSum, CheckSum);
IF Count < CountMAX THEN (* adjust short record -- shuffle down *)
j := 1;
FOR i := Sindex + 1 TO SrecMAX DO
Sdata[j] := Sdata[i];
INC (j);
END;
END;
LongPut (f, Sdata, Count * 2); (* S-record Code/Data *)
Complement; (* CheckSum *)
LongPut (f, CheckSum, 2);
WriteChar (f, ASCII.cr);
WriteChar (f, ASCII.lf);
LongInc (StartAddr, Count);
Sindex := SrecMAX;
Count := 0;
Boundary := FALSE;
CheckSum := LZero;
END DumpSdata;
PROCEDURE GetXdata;
(* Transfer Xdata into new Sdata line -- N.B.: Xdata stored in reverse *)
VAR
i : CARDINAL;
T : LONG;
BEGIN
i := 1;
T := LZero;
(* No need for either of the tests (CountMAX or Boundary) *)
(* used in AppendSdata. GetXdata is only ever called *)
(* after DumpSdata and is therefore only putting (up to 20) *)
(* HEX digits in an empty buffer (which could hold 32). *)
WHILE i < Xindex DO
Sdata[Sindex] := Xdata[i];
Sdata[Sindex - 1] := Xdata[i + 1];
T[2] := Sdata[Sindex]; T[1] := Sdata[Sindex - 1];
LongAdd (T, CheckSum, CheckSum);
INC (i, 2);
DEC (Sindex, 2);
INC (Count);
LongInc (TempAddr, 1);
END;
Xindex := 0;
END GetXdata;
PROCEDURE StartSrec (VAR f : File; SourceFN : ARRAY OF CHAR);
(* Writes S0 record (HEADER) and initializes *)
VAR
T : LONG; (* temporary *)
i : CARDINAL;
BEGIN
WriteChar (f, 'S');
WriteChar (f, '0');
CheckSum := LZero;
Count := Length (SourceFN) + 3; (* extra for Address & Checksum *)
CardToLong (Count, T);
LongPut (f, T, 2);
LongAdd (T, CheckSum, CheckSum);
LongPut (f, LZero, 4); (* Address is 4 digit, all zero, for S0 *)
i := 0;
WHILE SourceFN[i] # 0C DO
CardToLong (ORD (SourceFN[i]), T);
LongAdd (T, CheckSum, CheckSum);
LongPut (f, T, 2);
INC (i);
END;
Complement; (* CheckSum *)
LongPut (f, CheckSum, 2);
WriteChar (f, ASCII.cr);
WriteChar (f, ASCII.lf);
Sindex := SrecMAX;
Xindex := 0;
Count := 0;
Boundary := FALSE;
CheckSum := LZero;
StartAddr := LZero;
TempAddr := LZero;
END StartSrec;
PROCEDURE WriteSrecLine (VAR f : File;
AddrCnt, ObjOp, ObjSrc, ObjDest : LONG;
nA, nO, nS, nD : CARDINAL);
(* Collects Object Code -- Writes an S2 record to file if line is full *)
VAR
dummy : BOOLEAN;
BEGIN
IF nA = 0 THEN
RETURN; (* Nothing to add to S-record *)
END;
IF Xindex # 0 THEN
GetXdata; (* transfers Xdata into Sdata *)
END;
IF LongCompare (AddrCnt, TempAddr) # 0 THEN
DumpSdata (f);
END;
IF Count = 0 THEN
StartAddr := AddrCnt;
TempAddr := AddrCnt;
END;
dummy := AppendSdata (ObjOp, nO);
dummy := AppendSdata (ObjSrc, nS);
IF NOT AppendSdata (ObjDest, nD) THEN
DumpSdata (f);
END;
END WriteSrecLine;
PROCEDURE EndSrec (VAR f : File);
(* Finishes off any left-over (Partial) S2 line, *)
(* and then writes S8 record (TRAILER) *)
BEGIN
IF Xindex # 0 THEN
GetXdata;
END;
DumpSdata (f);
WriteChar (f, 'S'); (* Fixed format for S8 record *)
WriteChar (f, '8');
WriteChar (f, '0');
WriteChar (f, '4');
WriteChar (f, '0');
WriteChar (f, '0');
WriteChar (f, '0');
WriteChar (f, '0');
WriteChar (f, '0');
WriteChar (f, '0');
WriteChar (f, 'F');
WriteChar (f, 'C');
WriteChar (f, ASCII.cr);
WriteChar (f, ASCII.lf);
WriteChar (f, ASCII.cr);
WriteChar (f, ASCII.lf);
END EndSrec;
BEGIN (* Initialization *)
LongClear (LZero);
END Srecord.